 
package com.zdkj.subway.rca.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.zdkj.common.security.service.PigxUser;
import com.zdkj.common.security.util.SecurityUtils;
import com.zdkj.subway.rca.entity.SwCkCycleStockSale;
import com.zdkj.subway.rca.mapper.SwCkCycleStockSaleMapper;
import com.zdkj.subway.rca.service.SwCkCycleStockSaleService;
import com.zdkj.subway.rca.util.LocalDateConverter;
import com.zdkj.subway.rca.util.LocalDateTimeConverter;
import com.zdkj.subway.rca.util.MyBeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;


/**
 * 周期内库存售卖表
 *   1. 上日结存数量：车站车票库存日报表已经审核状态对应票种的上日结存数量
     2. 现库存张数：库存日报表的本日结存数量
     3. 售卖数量：库存日报表票种中的票房售出+TVM售出+网络售出数量合计（减去即时退换票的数量）
     4. 售卖金额：售卖数量*票种对应的单价-营销车票团购中的折扣率算出来的金额
     5. 收入统计合计：西安地铁收入调账日报表中，分票种的线路合计金额（预制票、应急票、日票、计次、纪念票）（加上转账、线下和团购的金额）
 * @author stw
 * @date 2020-11-24 11:11:45
 */
@Service
public class SwCkCycleStockSaleServiceImpl extends ServiceImpl<SwCkCycleStockSaleMapper, SwCkCycleStockSale> implements SwCkCycleStockSaleService {
    private static final Logger log = LoggerFactory.getLogger(SwCkCycleStockSaleServiceImpl.class);
    /**
     * 产生数据
     * @return
     */
    @Override
    public Boolean generate(String startDate,String endDate) throws Exception {

        //根据日期范围获取数据list
        List<Map<String,Object>> swStStockList = this.baseMapper.getSwStStockList(startDate,endDate);
        List<Map<String,Object>> swPmTicketCardTypeParamList = this.baseMapper.getSwPmTicketCardTypeParamList(startDate,endDate);
        List<Map<String,Object>> swCkStationDailyReportAdjustList = this.baseMapper.getSwCkStationDailyReportAdjustList(startDate,endDate);

        List<SwCkCycleStockSale> updaeList = new ArrayList<>();
        List<SwCkCycleStockSale> insertList = new ArrayList<>();

        PigxUser user = SecurityUtils.getUser();

        //循环swStStockList
        for(Map<String,Object> swStStock : swStStockList) {
            SwCkCycleStockSale insertObj = new SwCkCycleStockSale();
            insertObj.setLineCode((String)swStStock.get("LINE_CODE"));
            insertObj.setStatisticalTime(LocalDate.parse((String)swStStock.get("STATISTICAL_TIME"), DateTimeFormatter.ofPattern("yyyy-MM-dd")));
			String ticketTypeEn = (String)swStStock.get("TICKET_TYPE");
			//票种名称
            if("YZDCP".equals(ticketTypeEn)){
                insertObj.setTicketType("预制单程票");
            } else if("YJZP".equals(ticketTypeEn)){
                insertObj.setTicketType("应急纸票");
            } else if("YXCP1".equals(ticketTypeEn)){
                insertObj.setTicketType("纪念票");
            } else if("YXCP2".equals(ticketTypeEn)){
                insertObj.setTicketType("日票");
            } else if("YXCP3".equals(ticketTypeEn)){
                insertObj.setTicketType("计次票");
            }          
            
            //数据库老的
            SwCkCycleStockSale dbSwCkCycleStockSale = this.getOne(Wrappers.query(insertObj));
            if (dbSwCkCycleStockSale != null){
                insertObj.setId(dbSwCkCycleStockSale.getId());
            }
            //上日结存数量(张)（线网库存表）
            insertObj.setLastDayBalanceQuantity(((BigDecimal)swStStock.get("LAST_DAY_BALANCE_QUANTITY")).longValue());
            //现库存数量（线网库存表）
            insertObj.setCurrentStockQuantity(((BigDecimal)swStStock.get("CURRENT_STOCK_QUANTITY")).longValue());
            //售卖数量
            insertObj.setSoldQuantity(((BigDecimal)swStStock.get("SOLD_QUANTITY")).longValue());

            //BigDecimal ticketAount = (BigDecimal)ticketTypeMap.get("TICKET_AMOUNT"); //单价
			BigDecimal soldMoney = ((BigDecimal)swStStock.get("SOLD_MONEY"));
            //售卖金额（元）
            //insertObj.setSoldAmount(new BigDecimal(insertObj.getSoldQuantity()).multiply(ticketAount).subtract((BigDecimal)swStStock.get("SOLD_AMOUNT2")));
			//insertObj.setSoldAmount(soldMoney.subtract((BigDecimal)swStStock.get("SOLD_AMOUNT2")));
			insertObj.setSoldAmount(soldMoney);//不需要减去营销车票金额

            //收入金额（数据调整最终  统计）（元）
            Map<String,Object> incomeAmountMap =  geIncomeAmount(insertObj.getLineCode(),insertObj.getStatisticalTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")),swCkStationDailyReportAdjustList);
            BigDecimal incomeAmount = new BigDecimal(0);
            if(incomeAmountMap != null){

                if("YZDCP".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("PREFABRICATED_TICKET_AMOUNT");
                } else if("YJZP".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("EMERGENCY_TICKET_AMOUNT");
                } else if("YXCP1".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("COMMEMORATIVE_TICKET_SUB_TOTAL");
                } else if("YXCP2".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("DAILY_SUB_TOTAL");
					//log.info("日票金额============="+incomeAmount);
                } else if("YXCP3".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("TICKET_COUNTING");
                }
            }

            //收入金额（数据调整最终  统计）（元）
            insertObj.setIncomeAmount(incomeAmount);

            //差异金额（元）
            insertObj.setDifferenceAmount(insertObj.getIncomeAmount().subtract(insertObj.getSoldAmount()));

            //线路名称
            insertObj.setLineName((String)swStStock.get("LINE_NAME"));

            insertObj.setDeptId(user.getDeptId());
            insertObj.setCreatorId(user.getId());
            insertObj.setCreatorName(user.getNikeName());
            if(insertObj.getId() != null){
                updaeList.add(insertObj);
            } else {
                insertList.add(insertObj);
            }
        }
        boolean flag = false;
        boolean flag2 = false;
        if(!updaeList.isEmpty()){
            //合并同类票种
            //updaeList = sumTicketType(updaeList);
            flag = this.updateBatchById(updaeList);
        }
        if(!insertList.isEmpty()){
            //合并同类票种
            //insertList = sumTicketType(insertList);
            flag2 = this.saveBatch(insertList);
        }
        return  flag || flag2;
    }

	/*
	 @Override
    public Boolean generate(String startDate,String endDate) throws Exception {

        //根据日期范围获取数据list
        List<Map<String,Object>> swStStockList = this.baseMapper.getSwStStockList(startDate,endDate);
        List<Map<String,Object>> swPmTicketCardTypeParamList = this.baseMapper.getSwPmTicketCardTypeParamList(startDate,endDate);
        List<Map<String,Object>> swCkStationDailyReportAdjustList = this.baseMapper.getSwCkStationDailyReportAdjustList(startDate,endDate);

        List<SwCkCycleStockSale> updaeList = new ArrayList<>();
        List<SwCkCycleStockSale> insertList = new ArrayList<>();

        PigxUser user = SecurityUtils.getUser();

        //循环swStStockList
        for(Map<String,Object> swStStock : swStStockList) {
            SwCkCycleStockSale insertObj = new SwCkCycleStockSale();
            insertObj.setLineCode((String)swStStock.get("LINE_CODE"));
            insertObj.setStatisticalTime(LocalDate.parse((String)swStStock.get("STATISTICAL_TIME"), DateTimeFormatter.ofPattern("yyyy-MM-dd")));

            Map<String,Object> ticketTypeMap = getTicketType((String)swStStock.get("TICKET_TYPE_PARAM_EN"), swPmTicketCardTypeParamList);
            String ticketTypeEn = "";
            if(ticketTypeMap != null){
                ticketTypeEn = (String)ticketTypeMap.get("TICKET_TYPE");
            }
            //票种名称
            if("YZDCP".equals(ticketTypeEn)){
                insertObj.setTicketType("预制单程票");
            } else if("YJZP".equals(ticketTypeEn)){
                insertObj.setTicketType("应急纸票");
            } else if("YXCP1".equals(ticketTypeEn)){
                insertObj.setTicketType("纪念票");
            } else if("YXCP2".equals(ticketTypeEn)){
                insertObj.setTicketType("日票");
            } else if("YXCP3".equals(ticketTypeEn)){
                insertObj.setTicketType("计次票");
            }
            //数据库老的
            SwCkCycleStockSale dbSwCkCycleStockSale = this.getOne(Wrappers.query(insertObj));
            if (dbSwCkCycleStockSale != null){
                insertObj.setId(dbSwCkCycleStockSale.getId());
            }
            //上日结存数量(张)（线网库存表）
            insertObj.setLastDayBalanceQuantity(((BigDecimal)swStStock.get("LAST_DAY_BALANCE_QUANTITY")).longValue());
            //现库存数量（线网库存表）
            insertObj.setCurrentStockQuantity(((BigDecimal)swStStock.get("CURRENT_STOCK_QUANTITY")).longValue());
            //售卖数量
            insertObj.setSoldQuantity(((BigDecimal)swStStock.get("SOLD_QUANTITY")).longValue());

            BigDecimal ticketAount = (BigDecimal)ticketTypeMap.get("TICKET_AMOUNT"); //单价
            //售卖金额（元）
            insertObj.setSoldAmount(new BigDecimal(insertObj.getSoldQuantity()).multiply(ticketAount).subtract((BigDecimal)swStStock.get("SOLD_AMOUNT2")));

            //收入金额（数据调整最终  统计）（元）
            Map<String,Object> incomeAmountMap =  geIncomeAmount(insertObj.getLineCode(),insertObj.getStatisticalTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")),swCkStationDailyReportAdjustList);
            BigDecimal incomeAmount = new BigDecimal(0);
            if(incomeAmountMap != null){

                if("YZDCP".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("PREFABRICATED_TICKET_AMOUNT");
                } else if("YJZP".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("EMERGENCY_TICKET_AMOUNT");
                } else if("YXCP1".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("COMMEMORATIVE_TICKET_SUB_TOTAL");
                } else if("YXCP2".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("DAILY_SUB_TOTAL");
                } else if("YXCP3".equals(ticketTypeEn)){
                    incomeAmount = (BigDecimal)incomeAmountMap.get("TICKET_COUNTING");
                }
            }

            //收入金额（数据调整最终  统计）（元）
            insertObj.setIncomeAmount(incomeAmount);

            //差异金额（元）
            insertObj.setDifferenceAmount(insertObj.getIncomeAmount().subtract(insertObj.getSoldAmount()));

            //线路名称
            insertObj.setLineName((String)swStStock.get("LINE_NAME"));

            insertObj.setDeptId(user.getDeptId());
            insertObj.setCreatorId(user.getId());
            insertObj.setCreatorName(user.getNikeName());
            if(insertObj.getId() != null){
                updaeList.add(insertObj);
            } else {
                insertList.add(insertObj);
            }
        }
        boolean flag = false;
        boolean flag2 = false;
        if(!updaeList.isEmpty()){
            //合并同类票种
            updaeList = sumTicketType(updaeList);
            flag = this.updateBatchById(updaeList);
        }
        if(!insertList.isEmpty()){
            //合并同类票种
            insertList = sumTicketType(insertList);
            flag2 = this.saveBatch(insertList);
        }
        return  flag || flag2;
    }
	
	*/

    private  List<SwCkCycleStockSale> sumTicketType(List<SwCkCycleStockSale> list){
        Set<Map<String,Object>> set = new HashSet<>();

        for(SwCkCycleStockSale obj : list) {
            Map<String,Object> tmp = new HashMap<>();
            tmp.put("lineCode",obj.getLineCode());
            tmp.put("statisticalTime",obj.getStatisticalTime());
            tmp.put("ticketType",obj.getTicketType());
            set.add(tmp);
        }
        List<SwCkCycleStockSale> rtnList = new ArrayList<>();
        for(Map<String,Object> typeObj : set){
            SwCkCycleStockSale rtn = null;
            for(SwCkCycleStockSale obj : list) {
                if(typeObj.get("lineCode").equals(obj.getLineCode())
                        && typeObj.get("statisticalTime").equals(obj.getStatisticalTime())
                         && typeObj.get("ticketType").equals(obj.getTicketType())) {
                    if(rtn == null){
                        rtn = new SwCkCycleStockSale();
                        MyBeanUtils.copyProperties(obj,rtn);
                    } else {
                        rtn.setLastDayBalanceQuantity(rtn.getLastDayBalanceQuantity() + obj.getLastDayBalanceQuantity());
                        rtn.setCurrentStockQuantity(rtn.getCurrentStockQuantity() + obj.getCurrentStockQuantity());
                        rtn.setSoldQuantity(rtn.getSoldQuantity() + obj.getCurrentStockQuantity());
                        rtn.setSoldAmount(rtn.getSoldAmount().add(obj.getSoldAmount()));
                        rtn.setIncomeAmount(rtn.getIncomeAmount().add(obj.getIncomeAmount()));
                        rtn.setDifferenceAmount(rtn.getDifferenceAmount().add(obj.getDifferenceAmount()));
                    }
                }
            }
            rtnList.add(rtn);
        }
        return rtnList;
    }

    private Map<String,Object> getTicketType(String type,  List<Map<String,Object>> swPmTicketCardTypeParamList){
        if(swPmTicketCardTypeParamList == null || swPmTicketCardTypeParamList.isEmpty()) {
            return null;
        }
        for(Map<String,Object> map : swPmTicketCardTypeParamList) {
            if(type.equals(map.get("SUB_EN_NAME"))){
                return map;
            }
        }
        return null;
    }

    private Map<String,Object> geIncomeAmount(String lineCode,String statisticalTime,  List<Map<String,Object>> swCkStationDailyReportAdjustList){
        if(swCkStationDailyReportAdjustList == null || swCkStationDailyReportAdjustList.isEmpty()) {
            return null;
        }
        for(Map<String,Object> map : swCkStationDailyReportAdjustList) {			
            if(lineCode.equals(map.get("LINE_CODE")) && statisticalTime.equals(map.get("STATISTICAL_TIME"))) {
			
                return map;
            }
        }
        return null;
    }

    @Override
    public void exportSwCkCycleStockSale(String startDate, String endDate,String lineCode,String ticketType,HttpServletResponse response) {
        SwCkCycleStockSale swCkCycleStockSale = new SwCkCycleStockSale();
        swCkCycleStockSale.setLineCode(lineCode);
		if(ticketType!=null && !"".equals(ticketType)){
		  swCkCycleStockSale.setTicketType(ticketType);
		}

		QueryWrapper<SwCkCycleStockSale> lambdaQueryWrapper = Wrappers.query(swCkCycleStockSale);
        lambdaQueryWrapper.lambda().ge(StringUtils.isNotEmpty(startDate), SwCkCycleStockSale::getStatisticalTime, startDate).le( StringUtils.isNotEmpty(endDate),SwCkCycleStockSale::getStatisticalTime, endDate);
        lambdaQueryWrapper.orderByAsc("LINE_CODE");
		lambdaQueryWrapper.orderByAsc("STATISTICAL_TIME");	
		List<SwCkCycleStockSale> records = this.list(lambdaQueryWrapper);

		//
		/*
		QueryWrapper<SwCkCycleStockSale> queryWrappers = Wrappers.query(swCkCycleStockSale);
		queryWrappers.lambda().ge(StringUtils.isNotEmpty(startDate), SwCkCycleStockSale::getStatisticalTime, startDate)
        queryWrappers.orderByAsc("LINE_CODE");
        queryWrappers.orderByAsc("STATISTICAL_TIME");
        List<SwCkCycleStockSale> list = this.list(queryWrappers);
		//
        List<SwCkCycleStockSale> records = this.list(Wrappers.query(swCkCycleStockSale).lambda().ge(StringUtils.isNotEmpty(startDate), SwCkCycleStockSale::getStatisticalTime, startDate).le( StringUtils.isNotEmpty(endDate),SwCkCycleStockSale::getStatisticalTime, endDate));
        */
        InputStream excelTemplateIs = null;
        try {response.reset(); // 非常重要
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            final String fileName = URLEncoder.encode("周期内库存售卖", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");

            // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
            // {} 代表普通变量 {.} 代表是list的变量

            excelTemplateIs = this.getClass().getResourceAsStream("/static/excel/template/export/SwCkCycleStockSaleExcelTemplate.xlsx");

            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerConverter(new LocalDateTimeConverter()).registerConverter(new LocalDateConverter()).withTemplate(excelTemplateIs).build();
            WriteSheet writeSheet = EasyExcel.writerSheet("周期内库存售卖").build();
            // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
            // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
            // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
            // 如果数据量大 list不是最后一行 参照另一个
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
            excelWriter.fill(records, fillConfig, writeSheet);
            excelWriter.finish();

        } catch (Exception e) {
            e.printStackTrace();
            log.error("导出周期内库存售卖错误");
        } finally {
            if(excelTemplateIs != null){
                try {
                    excelTemplateIs.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }

            }
        }
    }
}
